#ifndef COLOR_H_XA6CCS1R
#define COLOR_H_XA6CCS1R

class Color3f
{
public:
    /** The red component. */
    GLfloat r;
	
    /** The green component. */
    GLfloat g;
	
    /** The blue component. */
    GLfloat b;
	
	
    /**
     * Default constructor. r, g, b not initialized.
     */
    Color3f ()
    {

    }
	
    
   /**
    * Copy constructor.
    * 
    * @param newColor The color to copy.
    */
   Color3f (const Color3f &newColor)
   {
       Color3f(newColor.r, newColor.g, newColor.b);
   }
	
	
    /**
     * The explicit constructor.
     * 
     * @param newR The new red value.
     * @param newG The new green value.
     * @param newB The new blue value.
     */
    Color3f (GLfloat newR, GLfloat newG, GLfloat newB)
    {
        r = newR;
        g = newG;
        b = newB;
    }
	
    /**
     * Sets this color to the value of inColor.
     * 
     * @param inColor the input color
     */
    void set (Color3f inColor)
    {
        r = inColor.r;
        g = inColor.g;
        b = inColor.b;
    }
	
	
    /**
     * Sets the value of this color to (inR, inG, inB)
     * 
     * @param inR the input red value
     * @param inG the input green value
     * @param inB the input blue value
     */
    void set (GLfloat inR, GLfloat inG, GLfloat inB)
    {
        r = inR;
        g = inG;
        b = inB;
    }
	
	
    /**
     * Sets this color as the product of the pairwise product of this color and
     * rhs.
     * 
     * @param rhs The right hand argument.
     */
    void scale (Color3f rhs)
    {
        r *= rhs.r;
        g *= rhs.g;
        b *= rhs.b;
    }
	
	
    /**
     * Scales each compoenent of this color by rhs.
     * 
     * @param rhs The scale value to use.
     */
    void scale (GLfloat rhs)
    {
        r *= rhs;
        g *= rhs;
        b *= rhs;
    }
	
	
    /**
     * Sets this color to the pairwise sum of this color and ths.
     * 
     * @param rhs the input color
     */
    void add (Color3f rhs)
    {
        r += rhs.r;
        g += rhs.g;
        b += rhs.b;
    }
	
	
    /**
     * Adds rhs scaled by scale pairwise to this color.
     * 
     * @param scale the scale factor
     * @param rhs the color to be scaled and added
     */
    void scaleAdd (GLfloat scale, Color3f rhs)
    {
        r += scale * rhs.r;
        g += scale * rhs.g;
        b += scale * rhs.b;
    }
	
	
    /**
     * Clamps the each component of this color to between [min,max]
     * 
     * @param min the minimum value
     * @param max the maximum value
     */
    void clamp (GLfloat minimum, GLfloat maximum)
    {
        r = max(min(r, maximum), minimum);
        g = max(min(g, maximum), minimum);
        b = max(min(b, maximum), minimum);
    }
	
	
    /**
     * This function returns an GLint which represents this color. The standard
     * RGB style bit packing is used and is compatible with
     * java.awt.BufferedImage.TYPE_INT_RGB. (ie - the low 8 bits, 0-7 are for
     * the blue channel, the next 8 are for the green channel, and the next 8
     * are for the red channel). The highest 8 bits are left untouched.
     * 
     * @return An integer representing this color.
     */
    GLint toInt ()
    {
        GLint iR, iG, iB;
		
        // Here we do the dumb thing and simply clamp then scale.
        // The "+ 0.5" is to achieve a "round to nearest" effect
        // since Java float to int casting simply truncates.
        iR = (GLint)(255.0 * max(min((double)r, 1.0), 0.0) + 0.5);
        iG = (GLint)(255.0 * max(min((double)g, 1.0), 0.0) + 0.5);
        iB = (GLint)(255.0 * max(min((double)b, 1.0), 0.0) + 0.5);
		
        // Bit packing at its finest
        return (iR << 16) | (iG << 8) | (iB << 0);
    }

};

std::ostream &operator<<(std::ostream &output, const Color3f &c) {
	cout << "Color3f(" << c.r << ", " << c.g << ", " << c.b << ')';
	return output;
}

#endif /* end of include guard: COLOR_H_XA6CCS1R */
